package com.fosss.search;

import java.util.Arrays;

/**
 * 斐波那契查找（黄金分割查找）
 */
public class FibonacciSearch {

    public static int maxSize=20;

    public static void main(String[] args) {
        int[] arr={1,2,3,45,65,110};
        int index = fibonacciSearch(arr, 110);
        System.out.println(index);
    }

    /**
     * 得到一个斐波那契数列
     * @return
     */
    public static int[] fib(){
        int[] f=new int[maxSize];
        f[0]=1;
        f[1]=1;
        for(int i=2;i<maxSize-1;i++){
            f[i]=f[i-1]+f[i-2];
        }
        return f;
    }

    /**
     *
     * @param arr 数组
     * @param value 要查找的值
     * @return 返回索引，找不到时返回-1
     */
    public static int fibonacciSearch(int[] arr,int value){
        int low=0;
        int high=arr.length - 1;
        //得到斐波那契数列
        int[] F=fib();

        int k=0;
        //获取到斐波那契分割数值的下标
        while(F[k]-1<high){
            k++;
        }

        int[] temp= Arrays.copyOf(arr,F[k]);
        //F[k]的值可能大于arr.length,temp的后几位数自动为零，需要将其设为arr[arr.length-1]
        for(int i=high+1;i< temp.length;i++){
            temp[i]=arr[high];
        }

        while (low <= high){
            int mid=low+F[k-1]-1;//!!!!!!!!!
            if(value<temp[mid]){
                high=mid-1;
                k--;
                //为什么是 k--
                //说明
                //1. 全部元素 = 前面的元素 + 后边元素
                //2. f[k] = f[k-1] + f[k-2]
                //因为 前面有 f[k-1]个元素,所以可以继续拆分 f[k-1] = f[k-2] + f[k-3]
                //即 在 f[k-1] 的前面继续查找 k--
                //即下次循环 mid = f[k-1-1]-1
            }else if(value>temp[mid]){
                low=mid+1;
                k-=2;
                //为什么是k -=2
                //说明
                //前面的元素是k-1,后面的元素是k-2
                //1. 全部元素 = 前面的元素 + 后边元素
                //2. f[k] = f[k-1] + f[k-2]
                //4. 即在f[k-2] 的前面进行查找 k -=2
            }else {
                //找到了
                // 因为你的temp数组后面补充了和原数组high位置一样的元素，如果查找到的是后面补充的元素，那么实际位置是high，而不是mid，mid已经数组下标越界了
                if(high<=mid){
                    return high;
                }else {
                    return mid;
                }
            }
        }
        return -1;//没有找到

    }
}














